//https://gitlab.com/mwiget/xdp-drop-test/-/tree/master
//https://stackoverflow.com/questions/64861121/ebpf-program-load-fails-without-verifier-log
#include <linux/bpf.h>
#include <linux/in.h>
#include <linux/if_ether.h>
#include <linux/ip.h>
#include <linux/types.h>
#include <stddef.h>
#include <memory.h>
#include <sys/types.h> 
#define SEC(NAME) __attribute__((section(NAME), used))


#define __uint(name, val) int(*(name))[val]
#define __type(name, val) typeof(val) *(name)
#define __array(name, val) typeof(val) *(name)[]

/* struct bpf_map_def {
     unsigned int type;
     unsigned int key_size;
     unsigned int value_size;
     unsigned int max_entries;
 };
 
struct bpf_map_def  SEC("maps") drop_map = {
    .type        = BPF_MAP_TYPE_ARRAY,
    .key_size    = sizeof(int),
    .value_size  = sizeof(int),
    .max_entries = 1,
};*/


struct {
	__uint(type, BPF_MAP_TYPE_ARRAY);
	__uint(key_size, sizeof(int));
	__uint(value_size, sizeof(int));
  __uint(max_entries, 1);
}drop_map SEC(".maps");


static void *(*bpf_map_lookup_elem)(void *map, void *key) =
	(void *) BPF_FUNC_map_lookup_elem;
SEC("drop_icmp")
int drop_icmp_func(struct xdp_md *ctx) {
  int key = 0;
  int *pkts_count=bpf_map_lookup_elem(&drop_map, &key);
  int ipsize = 0;

  void *data = (void *)(long)ctx->data;
  void *data_end = (void *)(long)ctx->data_end;

  struct ethhdr *eth = data;

  ipsize = sizeof(*eth);

  struct iphdr *ip = data + ipsize;
  ipsize += sizeof(struct iphdr);
  if (data + ipsize > data_end) {
    // not an ip packet, too short. Pass it on
    return XDP_PASS;
  }

  // technically, we should also check if it is an IP packet by
  // checking the ethernet header proto field ...
  if (ip->protocol == IPPROTO_ICMP) {
    if(pkts_count){
        (*pkts_count)++;
    }
    return XDP_DROP;
  }

  return XDP_PASS;
}

char __license[] SEC("license") = "GPL";
/*  reference
https://www.tigera.io/learn/guides/ebpf/ebpf-xdp/
https://cloud.tencent.com/developer/article/1770282
https://feisky.xyz/posts/2021-01-29-ebpf-program/
*/

/*
fatal error: sys/cdefs.h: No such file or directory
sudo apt-get --reinstall install libc6 libc6-dev
export C_INCLUDE_PATH=$C_INCLUDE_PATH:/usr/include/x86_64-linux-gnu/ 

clang -g -c -O2 -target bpf -c xdp-drop.c -o xdp-drop.o
llvm-objdump  -h  xdp-drop.o
objdump -h  xdp-drop.o


sudo ip link set dev wlxe0e1a997ab49 xdp obj xdp-drop.o sec drop_icmp
ip link show dev wlxe0e1a997ab49
sudo ip link set dev wlxe0e1a997ab49 xdp off
*/

